﻿using System;
using System.Collections.Generic;
using System.Globalization;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
using System.Windows.Data;
using System.Windows.Media;
using EpiNEXT.Core;
using EpiNEXT.Core.Fields;

namespace EpiNEXT.WPF
{
    public abstract class ControlFactoryBase
    {
        public BindingMode BindingMode { get; set; }
        public ControlCreationMode ControlCreationMode { get; set; }

        public ControlFactoryBase(BindingMode bindingMode = BindingMode.TwoWay, ControlCreationMode creationMode = ControlCreationMode.DataEntry)
        {
            this.BindingMode = bindingMode;
            this.ControlCreationMode = creationMode;
        }

        public virtual Dictionary<UIElement, IField> CreateControlsForPage(PageViewModel pageVM)
        {
            Dictionary<UIElement, IField> controlDictionary = new Dictionary<UIElement, IField>();

            foreach (IField field in pageVM.Fields)
            {
                List<UIElement> controls = CreateControlsForField(field as Field, pageVM.FormVM);
                foreach (UIElement element in controls)
                {
                    controlDictionary.Add(element, field);
                }
            }

            return controlDictionary;
        }

        protected System.Windows.Media.Color ConvertColor(EpiNEXT.Core.Fields.Properties.Color color)
        {
            if (color == null)
            {
                return Color.FromArgb(255, 255, 255, 255);
            }
            Color newColor = Color.FromArgb(color.A, color.R, color.G, color.B);
            return newColor;
        }

        protected System.Windows.Thickness ConvertThickness(EpiNEXT.Core.Fields.Properties.Thickness thickness)
        {
            if (thickness == null)
            {
                return new Thickness(0, 0, 0, 0);
            }
            Thickness newThickness = new Thickness(thickness.Left, thickness.Top, thickness.Right, thickness.Bottom);
            return newThickness;
        }

        protected virtual void SetListControlProperties(Selector input, DataField field)
        {
            Binding widthBinding = new Binding("SelectedForm.Fields[" + field.Name + "].InputWidth");

            widthBinding.Mode = BindingMode.TwoWay;

            input.TabIndex = field.TabIndex;
            input.IsTabStop = field.IsTabStop;
            //input.Width = field.InputWidth;
            input.SetBinding(Selector.WidthProperty, widthBinding);
            input.DisplayMemberPath = "DisplayUI";
            input.SelectedValuePath = "Store";

            input.BorderThickness = ConvertThickness(field.InputBorderThickness);
            input.FontSize = field.InputFontSize;
            //input.Foreground = new SolidColorBrush(field.InputForegroundColor);
            //input.Background = new SolidColorBrush(field.InputBackgroundColor);
            //input.BorderBrush = new SolidColorBrush(field.InputBorderColor);

            //input.Foreground.Freeze();
            //input.Background.Freeze();
            //input.BorderBrush.Freeze();

            input.IsSynchronizedWithCurrentItem = true;
        }

        protected abstract List<UIElement> CreateControlsForField(Field field, FormViewModel formVM);

        protected virtual void SetInputProperties(Control input, IField field)
        {
            FontFamily fontFamily = new FontFamily(field.PromptFontFamily);
            input.FontFamily = fontFamily;
            input.FontSize = field.InputFontSize;
            input.BorderThickness = ConvertThickness(field.InputBorderThickness);

            input.TabIndex = field.TabIndex;
            input.IsTabStop = field.IsTabStop;
        }

        protected virtual void SetPromptProperties(Label label, IField field)
        {
            FontWeight promptFontWeight = GetFontWeightFromString(field.PromptFontWeight);

            label.Width = Double.NaN;
            label.Height = Double.NaN;

            Binding promptLeftBinding = new Binding("SelectedForm.Fields[" + field.Name + "].PromptLeft");
            Binding promptTopBinding = new Binding("SelectedForm.Fields[" + field.Name + "].PromptTop");

            promptLeftBinding.Mode = BindingMode.TwoWay;
            promptTopBinding.Mode = BindingMode.TwoWay;

            label.SetBinding(Canvas.LeftProperty, promptLeftBinding);
            label.SetBinding(Canvas.TopProperty, promptTopBinding);

            Binding promptWidthBinding = new Binding("SelectedForm.Fields[" + field.Name + "].PromptWidth");
            Binding promptHeightBinding = new Binding("SelectedForm.Fields[" + field.Name + "].PromptHeight");

            promptWidthBinding.Mode = BindingMode.TwoWay;
            promptHeightBinding.Mode = BindingMode.TwoWay;

            label.SetBinding(Label.WidthProperty, promptWidthBinding);
            label.SetBinding(Label.HeightProperty, promptHeightBinding);

            //if (field.PromptWidth > 0)
            //{
            //    label.Width = field.PromptWidth;
            //}

            //if (field.PromptHeight > 0)
            //{
            //    label.Height = field.PromptHeight;
            //}

            FontFamily fontFamily = new FontFamily(field.PromptFontFamily);
            label.FontFamily = fontFamily; 

            if (field is CommandButtonField || field is RelateButtonField)
            {
                label.HorizontalContentAlignment = HorizontalAlignment.Center;
            }
            else
            {
                label.HorizontalContentAlignment = HorizontalAlignment.Left;
            }

            TextBlock tblock = new TextBlock();
            tblock.TextWrapping = TextWrapping.Wrap;
            tblock.TextTrimming = TextTrimming.CharacterEllipsis;
            tblock.Text = field.PromptText;
            tblock.FontWeight = promptFontWeight;
            tblock.Foreground = new SolidColorBrush(ConvertColor(field.PromptForegroundColor));
            tblock.Foreground.Freeze();
            tblock.HorizontalAlignment = HorizontalAlignment.Center;

            if (field.PromptFontSize.HasValue)
            {
                tblock.FontSize = field.PromptFontSize.Value;
                //if (tblock.FontSize < 15)
                //{
                //    TextOptions.SetTextFormattingMode(tblock, TextFormattingMode.Display);
                //}
                //else
                //{
                TextOptions.SetTextFormattingMode(tblock, TextFormattingMode.Ideal);
                //}
            }

            // This will pull the prompt text for the appropriate culture lookup as specified in the metadata
            if (field.PromptTranslations != null && field.PromptTranslations.Count > 0)
            {
                CultureInfo currentCulture = System.Threading.Thread.CurrentThread.CurrentUICulture;
                foreach (FieldTextPropertyTranslation promptTranslation in field.PromptTranslations)
                {
                    CultureInfo desiredCulture = new CultureInfo(promptTranslation.Culture);
                    if (desiredCulture.ToString() == currentCulture.ToString())
                    {
                        tblock.Text = promptTranslation.Text;
                    }
                }
            }

            label.Content = tblock;// field.PromptText;
            label.FontWeight = promptFontWeight;
            label.IsTabStop = false;
            if (ControlCreationMode == Core.ControlCreationMode.Design)
            {
                label.IsHitTestVisible = true;
            }
            else
            {
                label.IsHitTestVisible = false;
            }
            //label.Foreground = new SolidColorBrush(field.PromptForegroundColor);
            //label.Background = new SolidColorBrush(field.PromptBackgroundColor);
            //label.Background.Freeze();
        }

        protected virtual FontWeight GetFontWeightFromString(string fontWeightString)
        {
            switch (fontWeightString)
            {
                case "Black":
                    return FontWeights.Black;
                case "Bold":
                    return FontWeights.Bold;
                case "DemiBold":
                    return FontWeights.DemiBold;
                case "Heavy":
                    return FontWeights.Heavy;
                case "Light":
                    return FontWeights.Light;
                case "Medium":
                    return FontWeights.Medium;
                case "Normal":
                    return FontWeights.Normal;
                case "Regular":
                    return FontWeights.Regular;
                case "SemiBold":
                    return FontWeights.SemiBold;
                case "Thin":
                    return FontWeights.Thin;
                default:
                    return FontWeights.Normal;
            }
        }
    }
}
